#!/usr/bin/python
# -*- coding: utf-8 -*-

### BEGIN LICENSE
# Copyright (C) 2013 ~ 2015 National University of Defense Technology(NUDT) & Kylin Ltd
# Author: Kobe Lee
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3, as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranties of
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
# PURPOSE.  See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program.  If not, see <http://www.gnu.org/licenses/>.
### END LICENSE


from gi.repository import Gio, Gtk, Gdk, Notify, GObject, GdkPixbuf
from gi.repository import AppIndicator3 as AppIndicator
import sys, shutil, tempfile
reload(sys)
sys.setdefaultencoding("utf-8")
import commands, threading
import signal
import Queue
import types
import time
import string
from src.database import Database
from src.base import *
import logging, logging.handlers
from piston_mini_client import APIError
import httplib2
import datetime
from src.piston import WeatherPistonAPI

MySever = ("http://service.ubuntukylin.com:8001/weather/api/1.0/")
WeatherPistonAPI.default_service_root = MySever

from src.piston_remoter import PingBackPistonAPI
PINGBACK_SERVER = "http://service.ubuntukylin.com:8001/weather/"

INFO_TYPE            = 'type'
INFO_SETTING         = 'setting'
class Settings:
    db = None
    BASE_KEY             = 'apps.indicators.chinaweather'
    REFRESH_RATE         = 'refresh_rate'
    CITY_KEY             = 'city_id'
    TEMPERATURE_KEY      = 'show_temperature'
    PLACES               = 'places'

    INFO = {
        REFRESH_RATE : {
            INFO_TYPE : types.IntType,
            INFO_SETTING : 'refresh-rate'
        },
        CITY_KEY : {
            INFO_TYPE : types.StringType,
            INFO_SETTING : 'city-id'
        },
        TEMPERATURE_KEY : {
            INFO_TYPE : types.BooleanType,
            INFO_SETTING : 'show-temperature'
        },
        PLACES : {
            INFO_TYPE : types.DictType,
            INFO_SETTING: 'places'
        },
    }

    # Open the DB
    def prepare_settings_store(self):
        try:
            self.db = Gio.Settings.new(self.BASE_KEY)
        except Exception as e:
            print e

    def get_value(self, setting, return_id = False):
        setting_name = Settings.INFO[setting][INFO_SETTING]
        try:
            setting_type = Settings.INFO[setting][INFO_TYPE]
            get_func = {
                types.IntType:     self.db.get_int,
                types.StringType:  self.db.get_string,
                types.BooleanType: self.db.get_boolean,
                types.ListType:    self.db.get_string,
                types.DictType:    self.db.get_string,
                types.NoneType:    self.db.get_value,
            }[setting_type]
            return get_func(setting_name)
        except:
            return None

    def set_value(self, setting, value):
        value = '' if value is None else value
        value = str(value) if type(value) is types.DictType else value
        setting_name = Settings.INFO[setting][INFO_SETTING]
        try:
            setting_type = Settings.INFO[setting][INFO_TYPE]
            set_func = {
                types.IntType:     self.db.set_int,
                types.StringType:  self.db.set_string,
                types.BooleanType: self.db.set_boolean,
                types.ListType:    self.db.set_string,
                types.DictType:    self.db.set_string,
                types.NoneType:    self.db.set_value,
            }[setting_type]
            set_func(setting_name, value)
        except:
            log.debug( \
                "Settings: schema for '%s' not found, aborting" % setting)


class IndicatorWeather(threading.Thread):
#class IndicatorWeather():
    """ Indicator class """

    def __init__(self):
        threading.Thread.__init__(self)
        #self.setDaemon(True)
        #self.connect("delete-event", Gtk.main_quit)
        #self.connect('destroy', lambda q: Gtk.main_quit())
        self.server = WeatherPistonAPI(service_root=MySever)
        self.premoter = PingBackPistonAPI(service_root=PINGBACK_SERVER)
        self.main_icon = os.path.join
        self.winder = AppIndicator.Indicator.new("indicator-china-weather", "weather-indicator", AppIndicator.IndicatorCategory.OTHER)
        self.winder.set_status(AppIndicator.IndicatorStatus.ACTIVE)
        self.winder.set_attention_icon_full("weather-indicator-error", "Network connection unavailable")
        # self.winder = appindicator.Indicator("indicator-china-weather", "weather-indicator", appindicator.CATEGORY_OTHER)
        # self.winder.set_status(appindicator.STATUS_ACTIVE)
        # self.winder.set_attention_icon("weather-indicator-unknown")

        self.queue = Queue.PriorityQueue()
        Notify.init("indicator-china-weather")

        self.settings = Settings()
        self.settings.prepare_settings_store()
        self.city_id = self.settings.get_value("city_id")
        self.places = str(self.settings.get_value("places"))
        # trans str to dict
        self.places = eval(self.places)
        # 修复V1.0配置
        if type(self.places) != dict:
            self.places = {'101250101' : '长沙', '101010100' : '北京', '101020100' : '上海'}
            self.settings.set_value("places", str(self.places))
            self.city_id = '101250101'
            self.settings.set_value("city_id", self.city_id)

        self.rate = self.settings.get_value("refresh_rate")
        if self.rate in (False, None):
            default_value = 15
            self.settings.set_value("refresh_rate", default_value)
            self.rate = default_value
        self.temp = self.settings.get_value("show_temperature")
        if self.temp:
            self.label_guide = "100 ˚C"    # Guide for width of label
        else:
            self.label_guide = " "

        self.aboutdialog = None
        self.icon = None
        self.menu = None
        self.place = None
        self.actualization_time = 0

        if self.city_id in (False, None, '[]', ''):
            self.settings.set_value("places", '')
            self.menu_noplace()
        else:
            self.menu_normal()
            try:
                server_result = self.access_server_pingback()
                if server_result:
                    # when program start, it update_data
                    self.update_observe_data()
                    GObject.timeout_add_seconds(60, self.update_time)
                    self.submit_weather_pingback()
                else:
                    self.winder.set_icon("weather-indicator-error")
                    self.winder.set_status(AppIndicator.IndicatorStatus.ATTENTION)
                    self.winder.set_status(AppIndicator.IndicatorStatus.ACTIVE)
            except Exception as e:
                self.winder.set_icon("weather-indicator-error")
                self.winder.set_status(AppIndicator.IndicatorStatus.ATTENTION)
                self.winder.set_status(AppIndicator.IndicatorStatus.ACTIVE)

    # Show a menu if no places specified
    def menu_noplace(self):
        menu_noplace = Gtk.Menu()

        setup = Gtk.MenuItem("配置地点...")
        setup.connect("activate", self.prefs)
        menu_noplace.append(setup)
        setup.show()

        about = Gtk.MenuItem("关于")
        about.connect("activate", self.about)
        about.show()
        menu_noplace.append(about)

        # quit = Gtk.ImageMenuItem(gtk.STOCK_QUIT)
        quit = Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_QUIT, None)
        quit.connect("activate", self.quit)
        quit.show()
        menu_noplace.append(quit)

        self.winder.set_menu(menu_noplace)

        self.winder.set_icon("weather-indicator")
        self.winder.set_status(AppIndicator.IndicatorStatus.ATTENTION)
        self.winder.set_status(AppIndicator.IndicatorStatus.ACTIVE)

    # Show menu with data
    def menu_normal(self):
        self.menu = Gtk.Menu()

        ##City
        self.city_show = Gtk.MenuItem("城市")
        self.city_show.set_sensitive(True)
        self.city_show.show()
        self.menu.append(self.city_show)

        ##Weather
        self.weather_show = Gtk.MenuItem("天气")
        self.weather_show.set_sensitive(True)
        self.weather_show.show()
        self.menu.append(self.weather_show)
        
        ##Temperature
        self.temp_show = Gtk.MenuItem("当前气温")
        self.temp_show.set_sensitive(True)
        self.temp_show.show()
        self.menu.append(self.temp_show)

        self.temp_range = Gtk.MenuItem("湿度范围")
        self.temp_range.set_sensitive(True)
        self.temp_range.show()
        self.menu.append(self.temp_range)
        
        ##Humidity
        self.SD_show = Gtk.MenuItem("湿度")
        self.SD_show.set_sensitive(True)
        self.SD_show.show()
        self.menu.append(self.SD_show)

        ##Wind Direction
        self.WD_show = Gtk.MenuItem("风力风向")
        self.WD_show.set_sensitive(True)
        self.WD_show.show()
        self.menu.append(self.WD_show)

        self.pm_show = Gtk.MenuItem("空气质量")
        self.pm_show.set_sensitive(True)
        self.pm_show.show()
        self.menu.append(self.pm_show)

        ##Update Time
        self.time_show = Gtk.MenuItem("发布时间")
        self.time_show.set_sensitive(True)
        self.time_show.show()
        self.menu.append(self.time_show)

        ext_show = Gtk.MenuItem("天气预报")
        ext_show.connect("activate", self.show_forecast_weather)
        ext_show.show()
        self.menu.append(ext_show)

        self.place = self.places[self.city_id]

        self.menu_locations()

        ##Update Button
        self.refresh_show = Gtk.MenuItem("更新")
        self.refresh_show.connect("activate", self.update_observe_data)
        self.refresh_show.show()
        self.menu.append(self.refresh_show)

        ##Preferences
        prefs_show = Gtk.MenuItem("配置...")
        prefs_show.connect("activate", self.show_prefs_dialog)
        prefs_show.show()
        self.menu.append(prefs_show)

        ##About
        about_show = Gtk.MenuItem("关于")
        about_show.connect("activate", self.about)
        about_show.show()
        self.menu.append(about_show)

        ##Quit
        # quit = Gtk.ImageMenuItem(gtk.STOCK_QUIT)
        quit = Gtk.ImageMenuItem.new_from_stock(Gtk.STOCK_QUIT, None)
        quit.connect("activate", self.quit)
        quit.show()
        self.menu.append(quit)

        self.winder.set_menu(self.menu)
        self.update_label(" ")

    def on_city_changed(self, widget):
        if widget.get_active():
            self.place = widget.get_label()
            self.city_show.set_label(self.place)
            for (d,x) in self.places.items():
                if x == self.place:
                    self.city_id = d
                    break
            self.settings.set_value("city_id", self.city_id)
            # after change city, it update_data
            self.update_observe_data()

    def menu_locations(self):
        locations_menu = Gtk.Menu()
        locations_menu.set_sensitive(True)
        self.city_show.set_submenu(locations_menu)

        loco1 = Gtk.RadioMenuItem.new_with_label([], self.place)
        loco1.connect("toggled", self.on_city_changed)#, self.place
        loco1.show()
        locations_menu.append(loco1)
        group = loco1.get_group()
        # for place in self.places[1:]:
        for (d,x) in self.places.items():
            if x != self.place:
                loco = Gtk.RadioMenuItem.new_with_label(group, x)
                loco.connect("toggled", self.on_city_changed)#, place[0]
                loco.show()
                locations_menu.append(loco)
                group = loco.get_group()

    # Set a label of indicator
    def update_label(self, label):
        if (hasattr(self.winder, 'set_label')):
            self.winder.set_label(label, self.label_guide) if self.temp else self.winder.set_label(" ", " ")
            self.winder.set_status(AppIndicator.IndicatorStatus.ATTENTION)
            self.winder.set_status(AppIndicator.IndicatorStatus.ACTIVE)

    # Quit the applet
    def quit(self, widget, data=None):
        Gtk.main_quit()

    def show_notification(self, condition, icon, severe=False):
        if severe:
            n = Notify.Notification.new("异常提示",condition,icon)
        else:
            n = Notify.Notification.new(condition, "", icon)
        n.show()

    # -------------------------pingback-------------------------
    def submit_weather_pingback(self):
        last_time = get_last_time()
        now_time = datetime.datetime.now()

        if last_time in (None, ''):
            version_weather = VERSION
            distro, version_os = get_distro_info()
            try:
                pingback = self.premoter.submit_pingback_main(distro, version_os, version_weather, self.place)
            except Exception as e:
                return False
            if pingback:
                set_last_time(now_time.strftime('%Y-%m-%d'))#'%Y-%m-%d %H:%M:%S'
            return pingback
        else:
            last_time = datetime.datetime.strptime(last_time, '%Y-%m-%d')
            now_time = now_time.strftime('%Y-%m-%d')
            now_time = datetime.datetime.strptime(now_time, '%Y-%m-%d')
#            myseconds = (now_time - last_time).seconds
            delta = now_time - last_time#两个日期相隔的天数
            if (delta.days > 0):
                version_weather = VERSION
                distro, version_os = get_distro_info()
                try:
                    pingback = self.premoter.submit_pingback_main(distro, version_os, version_weather, self.place)
                except Exception as e:
                    return False
                if pingback:
                    set_last_time(now_time.strftime('%Y-%m-%d'))
                return pingback
            else:
                return False

    def access_server_pingback(self):
        pingback = self.premoter.access_server_pingback()
        return pingback

    def get_new_observe_weather(self, queue):
        self.now_temperature = ''
        observe_weather = None
        try:
            observe_weather = self.server.get_cma_observe_weather(self.city_id)
        except IOError as e:
            observe_weather = None
        except ValueError as e:
            observe_weather = None
        except APIError as e:
            observe_weather = None
        except httplib2.ServerNotFoundError:
            observe_weather = None
        except Exception as e:
            observe_weather = None
        if 'temp' in observe_weather.keys():
            self.now_temperature = observe_weather['temp']
        queue.put((10,observe_weather))

    def set_new_observe_weather(self, weather):
        self.ptime = weather['ptime']
        pint = string.atoi(self.ptime.split(':')[0])
        if pint > 7 or pint < 20:
            self.icon = weather_icons[weather['img1']]
        else :
            self.icon = weather_icons[weather['img2']]
        self.winder.set_icon(self.icon)
        self.city_show.set_label(weather['city'])
        self.weather_show.set_label(weather['weather'])
        if weather['temp'] in ("未知", "N/A", "", None):
            self.temp_show.hide()
        else:
            self.temp_show.show()
            self.temp_show.set_label('当前气温:' + weather['temp'] + '℃')
        self.temp_range.set_label('温度范围:' + weather['temp2'] + ' - ' + weather['temp1'])
        if weather['SD'] in ("未知", "N/A", "", None):
            self.SD_show.hide()
        else:
            self.SD_show.show()
            self.SD_show.set_label('湿度:' + weather['SD'])
        self.WD_show.set_label(weather['WD'] + weather['WS'])
        self.pm_show.set_label('空气质量:' + weather['aqi'])
        self.time_show.set_label('发布时间:' + weather['time'])
        if self.temp:
            if weather['temp'] in ("未知", "N/A", "", None):
                self.update_label(" ")
            else:
                self.update_label(weather['temp'] + '℃')

        # 不管获取实时天气成功与否，都在获取完成后更新时间去在规定的周期内重新获取
        self.actualization_time = 0
        self.update_time()
        self.schedule_weather_update()

    # update time
    def update_time(self):
        try:
            ut = int(round((time.time()-self.actualization_time)/60.0,0))
            if self.actualization_time == 0 or ut == 0:
                msg = '刚刚'
            else:
                msg = str(ut) + '分钟之前'
            self.refresh_show.set_label('更新'+' ('+msg+')')
            if (time.time()-self.actualization_time) > int(self.rate)*60:
                self.actualization_time = time.time()
        except Exception, e:
            log.debug("failed to update menu time value: '%s'" % e)
        return True

    # Schedule weather update
    def schedule_weather_update(self, rate_override = None):
        if hasattr(self, "rate_id"):
            GObject.source_remove(self.rate_id)
        if rate_override:
            self.rate_id = GObject.timeout_add(
                int(rate_override) * 60000, self.update_observe_data)
        else:
            self.rate_id = GObject.timeout_add(
                int(self.rate) * 60000, self.update_observe_data)

    def update_observe_data(self, widget = None):
        try:
            server_result = self.access_server_pingback()
            if server_result:
                observe_th = threading.Thread(target=self.get_new_observe_weather,
                                                  name='Fetcher',
                                                  args=(self.queue,))
                observe_th.setDaemon(True)
                observe_th.start()
                #observe_th.join()
                try:
                    num, weather = self.queue.get()
                    if weather not in (None, False):
                        self.set_new_observe_weather(weather)
                        self.submit_weather_pingback()
                    self.queue.task_done()
                except Queue.Empty:
                    self.show_notification("实时天气获取异常", "weather-indicator-unknown", severe=True)
        except Exception as e:
            self.show_notification("天气服务器连接失败", "weather-indicator-error", severe=True)

    # Open Preferences dialog
    def show_prefs_dialog(self, widget):
#        if ((not hasattr(self, 'prefswindow')) or (not self.prefswindow.get_visible())):
#            self.prefswindow = PreferencesDialog()
#            self.prefswindow.run()
#            self.prefswindow.destroy()
        if not hasattr(self, 'prefswindow'):
            self.prefswindow=PreferencesDialog("PreferencesDialog")
            self.prefswindow.show()
        else:
            self.prefswindow.show()

    def about(self, widget):
        if self.aboutdialog == None:
            self.aboutdialog = Gtk.AboutDialog()
            self.aboutdialog.set_program_name("优客天气")#Indicator China Weather
            self.aboutdialog.set_version(VERSION)
            self.aboutdialog.set_title("")

            ifile = open(os.path.join(os.path.abspath(os.path.curdir), "COPYING"), "r")
            self.aboutdialog.set_license(ifile.read().replace('\x0c', ''))
            ifile.close()

            self.aboutdialog.set_copyright("Copyright © 2013-2015 Ubuntu Kylin Team, xiangli@ubuntukylin.com")
            self.aboutdialog.set_comments("从 Ubuntu Kylin 天气服务端获取实时"
                                          "天气、六天或三天天气预报信息，数据"
                                          "均来自于中国气象局，添加人们日益关注"
                                          "的 PM2.5 指数，支持多城市切换和数据"
                                          "自动更新，分享每日生活指数和建议，为"                                          "用户日常起居和旅行提供参考。")

            self.aboutdialog.set_website("https://launchpad.net/indicator-china-weather")
            self.aboutdialog.set_website_label("优客天气主页")
            self.aboutdialog.set_documenters(['Zhang Zhao <vaguedream@hotmail.com>', 'yanwang <yiwuhehe@163.com>', 'binghe <kylinhebing@163.com>'])
            self.aboutdialog.set_artists(['Ou Yangyu'])
            logo_path = os.path.join(os.path.abspath(os.path.curdir), "indicator-china-weather.png")
            self.aboutdialog.set_logo(GdkPixbuf.Pixbuf.new_from_file(logo_path))

            self.aboutdialog.connect("response", self.about_close)
            self.aboutdialog.show()

    def about_close(self, widget, event=None):
        self.aboutdialog.destroy()
        self.aboutdialog = None

    def show_forecast_weather(self, widget):
        #try:
            #server_result = self.access_server_pingback()
            #if server_result:
        if ((not hasattr(self, 'forecast_weather')) or \
            (not self.forecast_weather.window.get_visible())):
                #if ((not hasattr(self, 'forecast_weather')) or \
                #    (not self.forecast_weather.window.get_visible())):
            self.forecast_weather = ExtendedForecast()
#            self.forecast_weather.builder.get_object("cityName").set_text(self.place)
            self.forecast_weather.show()
            #self.forecast_weather.window.show()
        elif not self.forecast_weather.window.is_active():
#            self.forecast_weather.builder.get_object("cityName").set_text(self.place)
            self.forecast_weather.window.set_visible(True)
        #except Exception as e:
        #    self.show_notification("天气服务器连接失败", "weather-indicator-error", severe=True)

class ForecastModel:
    def __init__(self, server, id):
        self.server = server
        self.city_id = id
        self.forecast6d_data = None
        self.forecast3d_data = None
        self.more_day_message = False
        self.next_page = False
        self.cur_date = "0000年00月00日"

    def prepare_forecast6d_data(self):
        try:
            self.cur_date = get_local_date()#用本地日期和天气数据里面的日期比较
            # self.cur_date = '2014年9月9日'
            self.forecast6d_data = self.server.get_cma_forecast6d_weather(self.city_id)
            # 比较当前本地日期和获取的六天天气预报中的日期，如果日期相同，则显示六天天气，否则去获取3天天气
            if str(self.forecast6d_data['date_y']) == self.cur_date:
                pass
            else:
                # 比较当前网络日期和获取的六天天气预报中的日期，如果日期相同，则显示六天天气，否则去获取3天天气
                self.cur_date = get_http_time()
                if str(self.forecast6d_data['date_y']) == self.cur_date:
                    pass
                else:
                    self.more_day_message = True
                    self.prepare_forecast3d_data()
        except ValueError as e:
            self.prepare_forecast3d_data()
        except APIError as e:
            self.prepare_forecast3d_data()
        except httplib2.ServerNotFoundError:
            self.prepare_forecast3d_data()
            self.server._offline_mode = True
        except:
            self.prepare_forecast3d_data()

    def prepare_forecast3d_data(self):
        try:
            self.forecast3d_data = self.server.get_cma_forecast3d_weather(self.city_id)
            if self.forecast3d_data not in (None, ''):
                self.next_page = True
        except ValueError as e:
            return
        except APIError as e:
            return
        except httplib2.ServerNotFoundError:
            self.server._offline_mode = True
            return
        except:
            return

    def get_forecast6d_data(self):
        return self.forecast6d_data

    def get_forecast3d_data(self):
        return self.forecast3d_data



class ExtendedForecast:
    def __init__(self):
        self.builder = Gtk.Builder()
        ui_path = os.path.join(os.path.abspath(os.path.curdir), "ui/Forecast.ui")
        self.builder.add_from_file(ui_path)
        self.window = self.builder.get_object("extended_forecast")
        self.builder.get_object("cityName").set_text(iw.place)
        self.builder.get_object('releaselabel').set_visible(False)
        self.builder.get_object('contentgrid').set_visible(False)
        self.builder.get_object('statuslabel').set_visible(False)
        self.builder.get_object('spinner').start()
#        self.window.set_size_request(540, 600)
        self.window.set_size_request(540, 200)
        add_drag_support(self.window)
        self.builder.connect_signals(self)
        self.window.connect("destroy", self.on_destroy)
        #self.window.setLevel(WINDOW_TOPLEVEL)
        #self.setup()
        while Gtk.events_pending():
            Gtk.main_iteration()
        #self.window.show_all()
#        self.window.show()
#        self.timeout_id = GObject.timeout_add(100, self.setup, None)
        #self.window.run()
        #self.window.destroy()

    def show(self):
        self.window.show()
        self.timeout_id = GObject.timeout_add(3000, self.setup, None)

    def setup(self, data):
        try:
            forecast = ForecastModel(iw.server, iw.city_id)
        except KeyError:
            log.error("generate forecast model failed...")
            return
        forecast.prepare_forecast6d_data()
        if forecast.next_page:
            forecast3d_data = forecast.get_forecast3d_data()
            self.builder.get_object('spinner').stop()
            if forecast3d_data in (None , ''):
#                self.builder.get_object("extended_forecast").set_title("天气预报获取失败！")
#                self.builder.get_object('maingrid').set_visible(False)
                self.builder.get_object('doinglabel').set_visible(False)
                self.builder.get_object('statuslabel').set_visible(True)
            else:
#                self.builder.get_object('maingrid').set_visible(True)
                self.show_3d_components()
                self.set_forecast3d_weather(forecast3d_data)
                self.builder.get_object('releaselabel').set_visible(True)
                self.builder.get_object('contentgrid').set_visible(True)
                self.builder.get_object('errorgrid').set_visible(False)
        else:
            forecast6d_data = forecast.get_forecast6d_data()
            self.builder.get_object('spinner').stop()
            if forecast6d_data == None:
                self.builder.get_object('doinglabel').set_visible(False)
                self.builder.get_object('statuslabel').set_visible(True)
#                self.builder.get_object("extended_forecast").set_title("天气预报获取失败！")
#                self.builder.get_object('contentgrid').set_visible(False)
            else:
#                self.builder.get_object('maingrid').set_visible(True)
                self.show_6d_components()
                self.set_forecast6d_weather(forecast6d_data)
                self.builder.get_object('releaselabel').set_visible(True)
                self.builder.get_object('contentgrid').set_visible(True)
                self.builder.get_object('errorgrid').set_visible(False)

    def show_6d_components(self):
        self.window.set_size_request(540, 600)
        self.builder.get_object('secondgrid').set_visible(True)
        self.builder.get_object('d6box').set_visible(True)
        self.builder.get_object('wind1').set_visible(True)
        self.builder.get_object('wind2').set_visible(True)
        self.builder.get_object('wind3').set_visible(True)
        self.builder.get_object('d3box').set_visible(False)
        self.builder.get_object('wind1_d').set_visible(False)
        self.builder.get_object('wind1_n').set_visible(False)
        self.builder.get_object('wind2_d').set_visible(False)
        self.builder.get_object('wind2_n').set_visible(False)
        self.builder.get_object('wind3_d').set_visible(False)
        self.builder.get_object('wind3_n').set_visible(False)
        self.builder.get_object('sun1').set_visible(False)
        self.builder.get_object('sun2').set_visible(False)
        self.builder.get_object('sun3').set_visible(False)

    def show_3d_components(self):
        self.window.set_size_request(540, 440)
        self.builder.get_object('secondgrid').set_visible(False)
        self.builder.get_object('d6box').set_visible(False)
        self.builder.get_object('wind1').set_visible(False)
        self.builder.get_object('wind2').set_visible(False)
        self.builder.get_object('wind3').set_visible(False)
        self.builder.get_object('d3box').set_visible(True)
        self.builder.get_object('wind1_d').set_visible(True)
        self.builder.get_object('wind1_n').set_visible(True)
        self.builder.get_object('wind2_d').set_visible(True)
        self.builder.get_object('wind2_n').set_visible(True)
        self.builder.get_object('wind3_d').set_visible(True)
        self.builder.get_object('wind3_n').set_visible(True)
        self.builder.get_object('sun1').set_visible(True)
        self.builder.get_object('sun2').set_visible(True)
        self.builder.get_object('sun3').set_visible(True)

    def set_forecast6d_weather(self, data):
        self.forecast_data = data
        self.builder.get_object("extended_forecast").set_title(self.forecast_data['city'] + " - 六天天气预报")
        self.builder.get_object("cityName").set_text(self.forecast_data['city'])
        self.builder.get_object("releaselabel").set_text("发布时间：" + "（农历" + self.forecast_data['date'] + "）" + self.forecast_data['date_y'] + self.forecast_data['fchh'] + " 时")

        self.builder.get_object("img1").set_from_file(self.get_weather_icon('img1'))
        self.builder.get_object("img2").set_from_file(self.get_weather_icon('img2'))
        self.builder.get_object("img3").set_from_file(self.get_weather_icon('img3'))
        self.builder.get_object("img4").set_from_file(self.get_weather_icon('img4'))
        self.builder.get_object("img5").set_from_file(self.get_weather_icon('img5'))
        self.builder.get_object("img6").set_from_file(self.get_weather_icon('img6'))
        self.builder.get_object("img7").set_from_file(self.get_weather_icon('img7'))
        self.builder.get_object("img8").set_from_file(self.get_weather_icon('img8'))
        self.builder.get_object("img9").set_from_file(self.get_weather_icon('img9'))
        self.builder.get_object("img10").set_from_file(self.get_weather_icon('img10'))
        self.builder.get_object("img11").set_from_file(self.get_weather_icon('img11'))
        self.builder.get_object("img12").set_from_file(self.get_weather_icon('img12'))

        self.builder.get_object("weather1").set_text(self.forecast_data['weather1'])
        self.builder.get_object("weather2").set_text(self.forecast_data['weather2'])
        self.builder.get_object("weather3").set_text(self.forecast_data['weather3'])
        self.builder.get_object("weather4").set_text(self.forecast_data['weather4'])
        self.builder.get_object("weather5").set_text(self.forecast_data['weather5'])
        self.builder.get_object("weather6").set_text(self.forecast_data['weather6'])

        self.builder.get_object("temp1").set_text(self.forecast_data['temp1'])
        self.builder.get_object("temp2").set_text(self.forecast_data['temp2'])
        self.builder.get_object("temp3").set_text(self.forecast_data['temp3'])
        self.builder.get_object("temp4").set_text(self.forecast_data['temp4'])
        self.builder.get_object("temp5").set_text(self.forecast_data['temp5'])
        self.builder.get_object("temp6").set_text(self.forecast_data['temp6'])

        self.builder.get_object("wind1").set_text(self.forecast_data['wind1'])
        self.builder.get_object("wind2").set_text(self.forecast_data['wind2'])
        self.builder.get_object("wind3").set_text(self.forecast_data['wind3'])
        self.builder.get_object("wind4").set_text(self.forecast_data['wind4'])
        self.builder.get_object("wind5").set_text(self.forecast_data['wind5'])
        self.builder.get_object("wind6").set_text(self.forecast_data['wind6'])

        self.time = time.strftime('%w', time.localtime(time.time()))
        #self.time = time.strftime('%Y-%m-%d', time.localtime(time.time()))
        labelofweek = ["week1", "week2", "week3", "week4", "week5", "week6"]
        dayofweek = ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"]
        for i in range(0,6):
            weektime = int(self.time) + i
            if weektime > 7:
                weektime -= 7
            if i == 0:
                self.builder.get_object(labelofweek[i]).set_text("今天  " + dayofweek[int(self.time)-1])
            else:
                self.builder.get_object(labelofweek[i]).set_text(dayofweek[weektime-1])

        self.builder.get_object("index_uv").set_text('紫外线指数：' + self.forecast_data['index_uv'])
        self.builder.get_object("index_xc").set_text('洗车指数：' + self.forecast_data['index_xc'])
        self.builder.get_object("index_tr").set_text('旅游指数：' + self.forecast_data['index_tr'])
        self.builder.get_object("index_co").set_text('舒适指数：' + self.forecast_data['index_co'])
        self.builder.get_object("index_cl").set_text('晨练指数：' + self.forecast_data['index_cl'])
        self.builder.get_object("index_ls").set_text('晾晒指数：' + self.forecast_data['index_ls'])
        self.builder.get_object("index_ag").set_text('过敏指数：' + self.forecast_data['index_ag'])
        self.builder.get_object("index_clothes").set_text('24小时穿衣指数：'  + self.forecast_data['index_clothes'])
        self.tooltip = self.builder.get_object("index_d")
        self.tooltip.set_text('温馨提示：' + self.forecast_data['index_d'])
        self.tooltip.set_tooltip_text(self.forecast_data['index_d'])

    def get_weather_icon(self, img):
        fchh = int(self.forecast_data['fchh'])
        if 6 <= fchh < 18:
            icons_day = ('img1', 'img3', 'img5', 'img7', 'img9', 'img11')
            icons_night = ('img2', 'img4', 'img6', 'img8', 'img10', 'img12')
        else:
            icons_day = ('img2', 'img4', 'img6', 'img8', 'img10', 'img12')
            icons_night = ('img1', 'img3', 'img5', 'img7', 'img9', 'img11')
        if img in icons_day:
            if self.forecast_data[img] == '99':
                return 'icons/weather/d' + self.forecast_data[icons_night[icons_day.index(img)]] + '.gif'
            else:
                return 'icons/weather/d' + self.forecast_data[img] + '.gif'
        elif img in icons_night:
            if self.forecast_data[img] == '99':
                return 'icons/weather/n' + self.forecast_data[icons_day[icons_night.index(img)]] + '.gif'
            else:
                return 'icons/weather/n' + self.forecast_data[img] + '.gif'



    def set_forecast3d_weather(self, data):
#        print "data->", data
#        data-> {u'f0': u'201507211800', u'fc0': u'', u'fc2': u'28', u'fc1': u'29', u'fa2': u'04', u'fa0': u'', u'fa1': u'04', u'fg0': u'', u'fg1': u'0', u'fg2': u'0', u'fd1': u'21', u'fd0': u'22', u'fd2': u'22', u'c13': u'116.407526', u'c12': u'100000', u'c11': u'010', u'c10': u'1', u'c17': u'8', u'fh0': u'0', u'c15': u'52.291420', u'c14': u'39.904030', u'fb2': u'02', u'fb1': u'04', u'fb0': u'04', u'ff2': u'0', u'ff1': u'0', u'ff0': u'0', u'c9': u'\u4e2d\u56fd', u'c3': u'\u5317\u4eac', u'c7': u'\u5317\u4eac', u'c5': u'\u5317\u4eac', u'fi2': u'05:04|19:37', u'fi0': u'05:02|19:38', u'fi1': u'05:03|19:37', u'fh1': u'0', u'c16': u'\u672a\u77e5', u'fe2': u'0', u'fe0': u'', u'fe1': u'0', u'fh2': u'0'}
        self.forecast_data = data
        self.builder.get_object("extended_forecast").set_title(self.forecast_data['c3'] + " - 三天天气预报")
        self.builder.get_object("cityName").set_text(self.forecast_data['c3'])
        release_time = self.forecast_data['f0']
        if len(release_time) == 12:
            show_time = release_time[0:4] + "年" + release_time[4:6] + "月" + release_time[6:8] + "日" + release_time[8:10] + ":" + release_time[10:12]
        else:
            show_time = release_time
        self.builder.get_object("releaselabel").set_text("发布时间：" + show_time)
        self.builder.get_object("level").set_text("城市级别：" + self.forecast_data['c10'])
        self.builder.get_object("altitude").set_text("海拔：" + self.forecast_data['c15'] + "米")
        self.builder.get_object("latlon").set_text("经度：" + self.forecast_data['c13'] + "°" + " 纬度："  + self.forecast_data['c14'] + "°")
        self.builder.get_object("areacode").set_text("区号：" + self.forecast_data['c11'])
        self.builder.get_object("zipcode").set_text("邮政编码：" + self.forecast_data['c12'])
        self.builder.get_object("radarstation").set_text("雷达站点：" + self.forecast_data['c16'])

        if len(release_time) > 8:
            anyday = int(datetime.datetime(int(release_time[0:4]), int(release_time[4:6]), int(release_time[6:8])).strftime("%w"))
            dayofweek = ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"]
            for i in range(0,3):
                weektime = anyday + i
                if weektime > 7:
                    weektime -= 7
                if i == 0:
                    show_text = "今天  " + dayofweek[weektime - 1]
                    self.builder.get_object("week1").set_text(show_text)
                elif i == 1:
                    show_text = dayofweek[weektime - 1]
                    self.builder.get_object("week2").set_text(show_text)
                elif i == 2:
                    show_text = dayofweek[weektime - 1]
                    self.builder.get_object("week3").set_text(show_text)


        if self.forecast_data['fa0'] in (False, None, ''):
            self.builder.get_object("img1").set_from_file('icons/weather/undefined_d.gif')
        else:
            self.builder.get_object("img1").set_from_file('icons/weather/d' + str(int(self.forecast_data['fa0'])) + '.gif')
        if self.forecast_data['fb0'] in (False, None, ''):
            self.builder.get_object("img2").set_from_file('icons/weather/undefined_n.gif')
        else:
            self.builder.get_object("img2").set_from_file('icons/weather/n' + str(int(self.forecast_data['fb0'])) + '.gif')

        if self.forecast_data['fa1'] in (False, None, ''):
            self.builder.get_object("img3").set_from_file('icons/weather/undefined_d.gif')
        else:
            self.builder.get_object("img3").set_from_file('icons/weather/d' + str(int(self.forecast_data['fa1'])) + '.gif')
        if self.forecast_data['fb1'] in (False, None, ''):
            self.builder.get_object("img4").set_from_file('icons/weather/undefined_n.gif')
        else:
            self.builder.get_object("img4").set_from_file('icons/weather/n' + str(int(self.forecast_data['fb1'])) + '.gif')

        if self.forecast_data['fa2'] in (False, None, ''):
            self.builder.get_object("img5").set_from_file('icons/weather/undefined_d.gif')
        else:
            self.builder.get_object("img5").set_from_file('icons/weather/d' + str(int(self.forecast_data['fa2'])) + '.gif')
        if self.forecast_data['fb2'] in (False, None, ''):
            self.builder.get_object("img6").set_from_file('icons/weather/undefined_n.gif')
        else:
            self.builder.get_object("img6").set_from_file('icons/weather/n' + str(int(self.forecast_data['fb2'])) + '.gif')


        if self.forecast_data['fc0'] in (False, None, ''):
            self.builder.get_object("temp1").set_text(self.forecast_data['fd0'] + '℃')
        else:
            self.builder.get_object("temp1").set_text(self.forecast_data['fc0'] + '℃ - ' + self.forecast_data['fd0'] + '℃')
        if self.forecast_data['fc1'] in (False, None, ''):
            self.builder.get_object("temp2").set_text(self.forecast_data['fd1'] + '℃')
        else:
            self.builder.get_object("temp2").set_text(self.forecast_data['fc1'] + '℃ - ' + self.forecast_data['fd1'] + '℃')
        if self.forecast_data['fc2'] in (False, None, ''):
            self.builder.get_object("temp3").set_text(self.forecast_data['fd2'] + '℃')
        else:
            self.builder.get_object("temp3").set_text(self.forecast_data['fc2'] + '℃ - ' + self.forecast_data['fd2'] + '℃')

        if self.forecast_data['fa0'] in [None, ""]:
            self.forecast_data['fa0'] = '99'
        if self.forecast_data['fa1'] in [None, ""]:
            self.forecast_data['fa1'] = '99'
        if self.forecast_data['fa2'] in [None, ""]:
            self.forecast_data['fa2'] = '99'
        if self.forecast_data['fb0'] in [None, ""]:
            self.forecast_data['fb0'] = '99'
        if self.forecast_data['fb1'] in [None, ""]:
            self.forecast_data['fb1'] = '99'
        if self.forecast_data['fb2'] in [None, ""]:
            self.forecast_data['fb2'] = '99'
        self.builder.get_object("weather1").set_text(weather_encode_table[self.forecast_data['fa0']] + '-' + weather_encode_table[self.forecast_data['fb0']])
        self.builder.get_object("weather2").set_text(weather_encode_table[self.forecast_data['fa1']] + '-' + weather_encode_table[self.forecast_data['fb1']])
        self.builder.get_object("weather3").set_text(weather_encode_table[self.forecast_data['fa2']] + '-' + weather_encode_table[self.forecast_data['fb2']])

        # wind of first day
        if self.forecast_data['fe0'] in (False, None, ''):
            wind_direction_d = 'N/A'
        else:
            wind_direction_d = wind_direction_encode_table[self.forecast_data['fe0']]
        if self.forecast_data['fg0'] in (False, None, ''):
            wind_power_d = 'N/A'
        else:
            wind_power_d = wind_power_encode_table[self.forecast_data['fg0']]
        if self.forecast_data['ff0'] in (False, None, ''):
            wind_direction_n = 'N/A'
        else:
            wind_direction_n = wind_direction_encode_table[self.forecast_data['ff0']]
        if self.forecast_data['fh0'] in (False, None, ''):
            wind_power_n = 'N/A'
        else:
            wind_power_n = wind_power_encode_table[self.forecast_data['fh0']]
        if wind_direction_d == 'N/A':
            self.builder.get_object("wind1_d").set_text("白天风力未知")
        else:
            self.builder.get_object("wind1_d").set_text("昼：" + wind_direction_d + ' ' + wind_power_d)
        if wind_power_n == 'N/A':
            self.builder.get_object("wind1_n").set_text("夜间风力未知")
        else:
            self.builder.get_object("wind1_n").set_text("夜：" + wind_direction_n + ' ' + wind_power_n)

        # wind of second day
        if self.forecast_data['fe1'] in (False, None, ''):
            wind_direction_d = 'N/A'
        else:
            wind_direction_d = wind_direction_encode_table[self.forecast_data['fe1']]
        if self.forecast_data['fg1'] in (False, None, ''):
            wind_power_d = 'N/A'
        else:
            wind_power_d = wind_power_encode_table[self.forecast_data['fg1']]
        if self.forecast_data['ff1'] in (False, None, ''):
            wind_direction_n = 'N/A'
        else:
            wind_direction_n = wind_direction_encode_table[self.forecast_data['ff1']]
        if self.forecast_data['fh1'] in (False, None, ''):
            wind_power_n = 'N/A'
        else:
            wind_power_n = wind_power_encode_table[self.forecast_data['fh1']]

        if wind_direction_d == 'N/A':
            self.builder.get_object("wind2_d").set_text("白天风力未知")
        else:
            self.builder.get_object("wind2_d").set_text("昼：" + wind_direction_d + ' ' + wind_power_d)
        if wind_power_n == 'N/A':
            self.builder.get_object("wind2_n").set_text("夜间风力未知")
        else:
            self.builder.get_object("wind2_n").set_text("夜：" + wind_direction_n + ' ' + wind_power_n)

        # wind of third day
        if self.forecast_data['fe2'] in (False, None, ''):
            wind_direction_d = 'N/A'
        else:
            wind_direction_d = wind_direction_encode_table[self.forecast_data['fe2']]
        if self.forecast_data['fg2'] in (False, None, ''):
            wind_power_d = 'N/A'
        else:
            wind_power_d = wind_power_encode_table[self.forecast_data['fg2']]
        if self.forecast_data['ff2'] in (False, None, ''):
            wind_direction_n = 'N/A'
        else:
            wind_direction_n = wind_direction_encode_table[self.forecast_data['ff2']]
        if self.forecast_data['fh2'] in (False, None, ''):
            wind_power_n = 'N/A'
        else:
            wind_power_n = wind_power_encode_table[self.forecast_data['fh2']]
        if wind_direction_d == 'N/A':
            self.builder.get_object("wind3_d").set_text("白天风力未知")
        else:
            self.builder.get_object("wind3_d").set_text("昼：" + wind_direction_d + ' ' + wind_power_d)
        if wind_power_n == 'N/A':
            self.builder.get_object("wind3_n").set_text("夜间风力未知")
        else:
            self.builder.get_object("wind3_n").set_text("夜：" + wind_direction_n + ' ' + wind_power_n)
        # sun
        self.builder.get_object("sun1").set_text("日出日落：" + self.forecast_data['fi0'])
        self.builder.get_object("sun2").set_text("日出日落：" + self.forecast_data['fi1'])
        self.builder.get_object("sun3").set_text("日出日落：" + self.forecast_data['fi2'])

    def close(self, widget, data=None):
        self.window.destroy()

    def on_destroy(self, widget):
        self.window.destroy()

    def on_minbtn_clicked(self, widget):
        self.window.iconify()

    def on_closebtn_clicked(self, widget):
        self.window.destroy()

class PreferencesDialog(GObject.GObject):
    def __init__( self, ui_file ):
        GObject.GObject.__init__(self)
#        self.builder=Gtk.Builder()
#        self.builder.add_from_file(ui_file)
        self.builder = get_builder(ui_file)
        self.dialog = self.builder.get_object("preferences_dialog")
        self.dialog.set_size_request(320, 300)
        add_drag_support(self.dialog)
        self.builder.get_object('rate').set_value(int(iw.rate))
        self.show_label = self.builder.get_object('checkbutton') #display temperature
        self.show_label.set_active(iw.temp)
        self.spinbutton_rate = self.builder.get_object('spinbutton_rate')
        self.spinbutton_rate.set_value(int(iw.rate))
        self.spinbutton_rate.set_wrap(False)
        self.builder.get_object('ok_btn').set_sensitive(True)
        for (d,x) in iw.places.items():
            self.builder.get_object('citieslist').append([x])
        # 将主界面的当前城市id保存下来
        self.pre_cur_id = iw.city_id
#        self.builder.connect_signals(self)
        self.builder.connect_signals({
            "on_closebutton_clicked": self.handle_close,
            "on_minbutton_clicked": self.handle_min,
            "on_addbtn_clicked":  self.handle_add_location,
            "on_deletebtn_clicked": self.handle_delete_location,
            "on_ok_btn_clicked":  self.handle_ok,
            "on_cancel_btn_clicked": self.handle_close,
        })

#    def run( self ):
#        self.dialog.show_all()

    def show(self, *args):
        self.dialog.show()

    def close(self, *args):
        self.dialog.hide()
        return True

    def handle_ok(self, widget, data=None):
        new_show_label = self.show_label.get_active()
        if (iw.temp != new_show_label):
            iw.temp = new_show_label
            iw.settings.set_value("show_temperature", new_show_label)
            if iw.temp:
                if iw.now_temperature in ("未知", "N/A", "", None):
                    iw.update_label(" ")
                else:
                    iw.update_label(iw.now_temperature  + '℃')
            else:
                iw.update_label(" ")

        rate_value = self.spinbutton_rate.get_text()
        if int(rate_value) != iw.rate:
            iw.settings.set_value("refresh_rate", int(rate_value))
            iw.rate = int(rate_value)
        self.close()

    def handle_close(self, *args):
        self.close()

    def handle_min(self, *args):
        self.dialog.iconify()

    def handle_add_location(self, widget):
#        if ((not hasattr(self, 'select_dialog')) or (not self.select_dialog.get_visible())):
#                self.select_dialog = SelectDialog()
#                self.select_dialog.run()
#                self.select_dialog.destroy()
        if not hasattr(self, 'select_dialog'):
            self.select_dialog = SelectDialog("SelectDialog")
            self.select_dialog.show()
        else:
            self.select_dialog.show()

    def handle_delete_location(self, widget):
        selection = self.builder.get_object('location_list').get_selection()
        model, iter = selection.get_selected()
        if iter != None:
            if len(iw.places) == 1:
                dialog = Gtk.MessageDialog(None, Gtk.DialogFlags.DESTROY_WITH_PARENT,Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE,"%s" % ("友情提示"))
                dialog.format_secondary_text("请您至少保留一个城市，谢谢！")
                dialog.run()
                dialog.destroy()
            else:
                # 在配置界面上删去该城市
                model.remove(iter)
                # 更改配置文件和更新menu
                remain_cities = list()
                item = self.builder.get_object('citieslist').get_iter_first()
                while (item != None):
                    remain_cities.append(self.builder.get_object('citieslist').get_value(item, 0))
                    item = self.builder.get_object('citieslist').iter_next(item)

                # conf_cities = iw.settings.get_value("places")
                # 取剩下列表和配置列表的差集，即是被删除的那个城市名
                conf_cities = list()
                for (d,x) in iw.places.items():
                    conf_cities.append(x)
                del_list = list(set(conf_cities).difference(set(remain_cities)))
                del_city = del_list[0]
                del_id = ''
                new_places_dict = {}
                for (d,x) in iw.places.items():
                    if x == del_city:
                        del_id = d
                    else:
                        new_places_dict[d] = x
                if del_id == self.pre_cur_id:# need to change self.pre_cur_id
                    iw.places = new_places_dict
                    self.pre_cur_id = new_places_dict.keys()[0]
                    iw.city_id = self.pre_cur_id
                    iw.settings.set_value("places", str(new_places_dict))
                    iw.settings.set_value("city_id", str(iw.city_id))
                    iw.menu_normal()
                    iw.update_observe_data()
                else:
                    iw.places = new_places_dict
                    iw.settings.set_value("places", str(new_places_dict))
                    iw.menu_normal()
                    iw.update_observe_data()

#class PreferencesDialog(Gtk.Dialog):
#    """ Class for preferences dialog """
#    __gtype_name__ = "PreferencesDialog"

#    # Creating a new preferences dialog
#    def __new__(cls):
#        builder = get_builder('PreferencesDialog')
#        new_object = builder.get_object("preferences_dialog")
#        new_object.finish_initializing(builder)
#        return new_object

#    # Fill in preferences dialog with currect data
#    def finish_initializing(self, builder):
#        self.builder = builder
#        self.builder.get_object('rate').set_value(int(iw.rate))
#        self.show_label = self.builder.get_object('show_label') #display temperature
#        self.show_label.set_active(iw.temp)
#        self.spinbutton_rate = self.builder.get_object('spinbutton_rate')
#        self.spinbutton_rate.set_value(int(iw.rate))
#        self.builder.get_object('ok_button').set_sensitive(True)
#        for (d,x) in iw.places.items():
#            self.builder.get_object('citieslist').append([x])
#        # 将主界面的当前城市id保存下来
#        self.pre_cur_id = iw.city_id
#        self.builder.connect_signals(self)

#    # 'Remove' clicked - remove location from list
#    def on_remove_location(self, widget):
#        selection = self.builder.get_object('location_list').get_selection()
#        model, iter = selection.get_selected()
#        if iter != None:
#            if len(iw.places) == 1:
#                dialog = Gtk.MessageDialog(None, Gtk.DialogFlags.DESTROY_WITH_PARENT,Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE,"%s" % ("友情提示"))
#                dialog.format_secondary_text("请您至少保留一个城市，谢谢！")
#                dialog.run()
#                dialog.destroy()
#            else:
#                # 在配置界面上删去该城市
#                model.remove(iter)
#                # 更改配置文件和更新menu
#                remain_cities = list()
#                item = self.builder.get_object('citieslist').get_iter_first()
#                while (item != None):
#                    remain_cities.append(self.builder.get_object('citieslist').get_value(item, 0))
#                    item = self.builder.get_object('citieslist').iter_next(item)

#                # conf_cities = iw.settings.get_value("places")
#                # 取剩下列表和配置列表的差集，即是被删除的那个城市名
#                conf_cities = list()
#                for (d,x) in iw.places.items():
#                    conf_cities.append(x)
#                del_list = list(set(conf_cities).difference(set(remain_cities)))
#                del_city = del_list[0]
#                del_id = ''
#                new_places_dict = {}
#                for (d,x) in iw.places.items():
#                    if x == del_city:
#                        del_id = d
#                    else:
#                        new_places_dict[d] = x
#                if del_id == self.pre_cur_id:# need to change self.pre_cur_id
#                    iw.places = new_places_dict
#                    self.pre_cur_id = new_places_dict.keys()[0]
#                    iw.city_id = self.pre_cur_id
#                    iw.settings.set_value("places", str(new_places_dict))
#                    iw.settings.set_value("city_id", str(iw.city_id))
#                    iw.menu_normal()
#                    iw.update_observe_data()
#                else:
#                    iw.places = new_places_dict
#                    iw.settings.set_value("places", str(new_places_dict))
#                    iw.menu_normal()
#                    iw.update_observe_data()


#    # 'Add' clicked - create a new Assistant
#    def on_add_location(self, widget):
#        if ((not hasattr(self, 'select_dialog')) or (not self.select_dialog.get_visible())):
#		    self.select_dialog = SelectDialog()
#                    self.select_dialog.run()
#                    self.select_dialog.destroy()
#		    #self.select_dialog.show()

#	# 'OK' clicked - save settings
#    def ok(self, widget, data=None):
#        new_show_label = self.show_label.get_active()
#        if (iw.temp != new_show_label):
#            iw.temp = new_show_label
#            iw.settings.set_value("show_temperature", new_show_label)
#            if iw.temp:
#                if iw.now_temperature in ("未知", "N/A", "", None):
#                    iw.update_label(" ")
#                else:
#                    iw.update_label(iw.now_temperature  + '℃')
#                # iw.update_label(iw.weather_data['temp'] + '℃')
#            else:
#                iw.update_label(" ")

#        rate_value = self.spinbutton_rate.get_text()
#        if int(rate_value) != iw.rate:
#            iw.settings.set_value("refresh_rate", int(rate_value))
#            iw.rate = int(rate_value)
#        self.destroy()

#    # 'Cancel' click - forget all changes
#    def cancel(self, widget, data=None):
#        self.destroy()


class SelectDialog(GObject.GObject):
    def __init__(self, ui_file):
        GObject.GObject.__init__(self)
#        self.builder=Gtk.Builder()
#        self.builder.add_from_file(ui_file)
        self.builder = get_builder(ui_file)
        self.dialog = self.builder.get_object("select_dialog")
        self.dialog.set_size_request(400, 200)
        self.dialog.set_modal(True)
        self.dialog.set_keep_above(True)
#        self.dialog.set_position(gtk.WIN_POS_CENTER)
        add_drag_support(self.dialog)
        self.builder.connect_signals(self)
        self.select_dialog = self.builder.get_object("select_dialog")
        self.province_comb = self.builder.get_object("province_combobox")
        self.city_comb = self.builder.get_object("city_combobox")
        self.county_comb = self.builder.get_object("county_combobox")
        self.db = Database()
        self.init_combobox_items()
#        self.builder.connect_signals({
#            "on_closebutton_clicked": self.handle_close,
#            "on_province_combobox_changed":  self.handle_province_combobox_changed,
#            "on_city_combobox_changed": self.handle_city_combobox_changed,
#            "on_ok_btn_clicked":  self.handle_ok,
#            "on_cancel_btn_clicked": self.handle_close,
#        })

    def init_combobox_items(self):
        self.province_store = Gtk.ListStore(str)
        self.city_store = Gtk.ListStore(str)
        self.county_store = Gtk.ListStore(str)

        self.province_comb.set_sensitive(True)
        self.province_comb.set_model(self.province_store)
        for word in province_list:
            self.province_store.append([word])
        self.province_comb.set_active(0)
        # self.province_comb.popup()
        cell = Gtk.CellRendererText()
        self.province_comb.pack_start(cell, True)
        self.province_comb.add_attribute(cell, 'text', 0)

        self.city_comb.set_sensitive(True)
        self.city_comb.set_model(self.city_store)
        self.city_comb.set_active(0)
        self.city_comb.popup()
        cell = Gtk.CellRendererText()
        self.city_comb.pack_start(cell, True)
        self.city_comb.add_attribute(cell, 'text', 0)

        self.county_comb.set_sensitive(True)
        self.county_comb.set_model(self.county_store)
        self.county_comb.set_active(0)
        self.county_comb.popup()
        cell = Gtk.CellRendererText()
        self.county_comb.pack_start(cell, True)
        self.county_comb.add_attribute(cell, 'text', 0)

    def on_closebutton_clicked(self, widget):
        self.close()

    def show(self, *args):
        self.dialog.show()

    def close(self, *args):
        self.dialog.hide()
        return True

    def on_province_combobox_changed(self, widget):
        tree_iter = self.province_comb.get_active_iter()
        if tree_iter != None:
            model = self.province_comb.get_model()
            province = model[tree_iter][0]
            db_list = self.db.search_city_table(province)
            self.city_store.clear()
            for line in db_list:
                self.city_store.append([line[0]])
            self.city_comb.set_active(0)

    def on_city_combobox_changed(self, widget):
        p_tree_iter = self.province_comb.get_active_iter()
        c_tree_iter = self.city_comb.get_active_iter()
        if p_tree_iter != None and c_tree_iter != None:
            model_p = self.province_comb.get_model()
            province = model_p[p_tree_iter][0]
            model_c = self.city_comb.get_model()
            city = model_c[c_tree_iter][0]
            db_list = self.db.search_counties(province, city)
            self.county_store.clear()
            for line in db_list:
                self.county_store.append([line[0]])
            self.county_comb.set_active(0)

    # 'OK' clicked - save settings
    def on_ok_btn_clicked(self, widget, data=None):
        province_tree_iter = self.province_comb.get_active_iter()
        city_tree_iter = self.city_comb.get_active_iter()
        county_tree_iter = self.county_comb.get_active_iter()
        if province_tree_iter != None and city_tree_iter != None and county_tree_iter != None:
            model_p = self.province_comb.get_model()
            province = model_p[province_tree_iter][0]
            model_city = self.city_comb.get_model()
            city = model_city[city_tree_iter][0]
            model_county = self.county_comb.get_model()
            county = model_county[county_tree_iter][0]
        if province is not None and city is not None and county is not None:
            selected_id = self.db.search_id(province, city, county)
            selected_id = selected_id[0][0]
            if selected_id in iw.places.keys():
                dialog = Gtk.MessageDialog(None, Gtk.DialogFlags.DESTROY_WITH_PARENT,Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE,"%s" % ("城市重复"))
                dialog.format_secondary_text("您选择的城市已经存在，请重新选择或退出！")
                dialog.run()
                dialog.destroy()
            else:
                # 将新增城市添加到配置页面的城市列表中
                iw.prefswindow.builder.get_object('citieslist').append([county])
                # 将新增城市id和名字写入对应的dict中，然后写入配置
                iw.places[selected_id] = county
                iw.settings.set_value("places", str(iw.places))
                # 将新增城市的id告诉配置界面程序
                iw.prefswindow.pre_cur_id = selected_id
                iw.city_id = selected_id
                iw.settings.set_value("city_id", str(iw.city_id))
                iw.menu_normal()
                iw.update_observe_data()
#                self.dialog.destroy()
#                self.dialog.hide()
                self.close()
        else:
            dialog = Gtk.MessageDialog(None, Gtk.DialogFlags.DESTROY_WITH_PARENT,Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE,"%s" % ("选择城市"))
            dialog.format_secondary_text("请根据省市县三级选择您需要的城市！")
            dialog.run()
            dialog.destroy()

    # 'Cancel' click - forget all changes
    def on_cancel_btn_clicked(self, widget, data=None):
#        self.dialog.destroy()
#        self.dialog.hide()
        self.close()

#class SelectDialog(Gtk.Dialog):
#    """ Class for select dialog """
#    __gtype_name__ = "SelectDialog"

#    # Creating a new select dialog
#    def __new__(cls):
#        builder = get_builder('SelectDialog')
#        new_object = builder.get_object("select_dialog")
#        new_object.finish_initializing(builder)
#        return new_object

#    def finish_initializing(self, builder):
#        self.builder = builder
#        self.builder.connect_signals(self)
#        self.select_dialog = self.builder.get_object("select_dialog")
#        self.province_comb = self.builder.get_object("province_combobox")
#        self.city_comb = self.builder.get_object("city_combobox")
#        self.county_comb = self.builder.get_object("county_combobox")
#        self.db = Database()
#        self.init_combobox_items()

#    def init_combobox_items(self):
#        self.province_store = Gtk.ListStore(str)
#        self.city_store = Gtk.ListStore(str)
#        self.county_store = Gtk.ListStore(str)

#        self.province_comb.set_sensitive(True)
#        self.province_comb.set_model(self.province_store)
#        for word in province_list:
#            self.province_store.append([word])
#        self.province_comb.set_active(0)
#        # self.province_comb.popup()
#        cell = Gtk.CellRendererText()
#        self.province_comb.pack_start(cell, True)
#        self.province_comb.add_attribute(cell, 'text', 0)

#        self.city_comb.set_sensitive(True)
#        self.city_comb.set_model(self.city_store)
#        self.city_comb.set_active(0)
#        self.city_comb.popup()
#        cell = Gtk.CellRendererText()
#        self.city_comb.pack_start(cell, True)
#        self.city_comb.add_attribute(cell, 'text', 0)

#        self.county_comb.set_sensitive(True)
#        self.county_comb.set_model(self.county_store)
#        self.county_comb.set_active(0)
#        self.county_comb.popup()
#        cell = Gtk.CellRendererText()
#        self.county_comb.pack_start(cell, True)
#        self.county_comb.add_attribute(cell, 'text', 0)


#    def on_province_combobox_changed(self, widget):
#        tree_iter = self.province_comb.get_active_iter()
#        if tree_iter != None:
#            model = self.province_comb.get_model()
#            province = model[tree_iter][0]
#            db_list = self.db.search_city_table(province)
#            self.city_store.clear()
#            for line in db_list:
#                self.city_store.append([line[0]])
#            self.city_comb.set_active(0)

#    def on_city_combobox_changed(self, widget):
#        p_tree_iter = self.province_comb.get_active_iter()
#        c_tree_iter = self.city_comb.get_active_iter()
#        if p_tree_iter != None and c_tree_iter != None:
#            model_p = self.province_comb.get_model()
#            province = model_p[p_tree_iter][0]
#            model_c = self.city_comb.get_model()
#            city = model_c[c_tree_iter][0]
#            db_list = self.db.search_counties(province, city)
#            self.county_store.clear()
#            for line in db_list:
#                self.county_store.append([line[0]])
#            self.county_comb.set_active(0)

#    # 'OK' clicked - save settings
#    def ok(self, widget, data=None):
#        province_tree_iter = self.province_comb.get_active_iter()
#        city_tree_iter = self.city_comb.get_active_iter()
#        county_tree_iter = self.county_comb.get_active_iter()
#        if province_tree_iter != None and city_tree_iter != None and county_tree_iter != None:
#            model_p = self.province_comb.get_model()
#            province = model_p[province_tree_iter][0]
#            model_city = self.city_comb.get_model()
#            city = model_city[city_tree_iter][0]
#            model_county = self.county_comb.get_model()
#            county = model_county[county_tree_iter][0]
#        if province is not None and city is not None and county is not None:
#            selected_id = self.db.search_id(province, city, county)
#            selected_id = selected_id[0][0]
#            if selected_id in iw.places.keys():
#                dialog = Gtk.MessageDialog(None, Gtk.DialogFlags.DESTROY_WITH_PARENT,Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE,"%s" % ("城市重复"))
#                dialog.format_secondary_text("您选择的城市已经存在，请重新选择或退出！")
#                dialog.run()
#                dialog.destroy()
#            else:
#                # 将新增城市添加到配置页面的城市列表中
#                iw.prefswindow.builder.get_object('citieslist').append([county])
#                # 将新增城市id和名字写入对应的dict中，然后写入配置
#                iw.places[selected_id] = county
#                iw.settings.set_value("places", str(iw.places))
#                # 将新增城市的id告诉配置界面程序
#                iw.prefswindow.pre_cur_id = selected_id
#                iw.city_id = selected_id
#                iw.settings.set_value("city_id", str(iw.city_id))
#                iw.menu_normal()
#                iw.update_observe_data()
#                self.destroy()
#        else:
#            dialog = Gtk.MessageDialog(None, Gtk.DialogFlags.DESTROY_WITH_PARENT,Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE,"%s" % ("选择城市"))
#            dialog.format_secondary_text("请根据省市县三级选择您需要的城市！")
#            dialog.run()
#            dialog.destroy()

#    # 'Cancel' click - forget all changes
#    def cancel(self, widget, data=None):
#        self.destroy()


# ensure that single instance of applet is running for each user
class SingleInstance(object):
    
    #Initialize, specifying a path to store pids
    def __init__(self,pidPath):
        
        self.pidPath = pidPath
        if os.path.exists(pidPath):
            log.debug("SingleInstance: pid file %s exists" % pidPath)
            # Make sure it is not a "stale" pidFile
            pid = open(pidPath, 'r').read().strip()
            # Check list of running pids, if not running it is stale so overwrite

            pidRunning = commands.getoutput('ls -1 /proc | grep ^%s$' % pid)
            log.debug("SingleInstance: pid running %s" % pidRunning)
            self.lasterror = True if pidRunning else False
        else:
            self.lasterror = False

        if not self.lasterror:
            log.debug("SingleInstance: writing new pid %s" % str(os.getpid()))
            # Create a temp file, copy it to pidPath and remove temporary file
            (fp, temp_path) = tempfile.mkstemp()
            try:
                os.fdopen(fp, "w+b").write(str(os.getpid()))
                shutil.copy(temp_path, pidPath)
                os.unlink(temp_path)
            except Exception as e:
                log.error("SingleInstance: exception while renaming '%s' to '%s':\n %s" % (temp_path, pidPath, str(e)))

    def is_already_running(self):
         return self.lasterror

    def __del__(self):
         if not self.lasterror:
            log.debug("SingleInstance: deleting %s" % self.pidPath)
            os.unlink(self.pidPath)

def main():
    #Gtk.timeout_add(500, testkobe)
    Gtk.main()
    #exit(0)
    #Gtk.mainloop()
    return 0

def handler(signum, frame):
    Gtk.main_quit()
    sys.exit()

class Watcher:
    def __init__(self):
        self.child = os.fork()
        if self.child == 0:
            return 
        else:
            self.watch()
    def watch(self):
        try:
            os.wait()
        except KeyboardInterrupt:
            print 'KeyBoardInterrupt------'
            self.kill()
        sys.exit()
    def kill(self):
        try:
            os.kill(self.child, signal.SIGKILL)
        except OSError: pass

def load_css_sheet_sytle():
    screen = Gdk.Screen().get_default()
    css_provider = Gtk.CssProvider()
    css_provider.load_from_path("./icons/weather.css")
    context = Gtk.StyleContext()
    context.add_provider_for_screen(screen, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_USER)

if __name__ == "__main__":
    #signal.signal(signal.SIGINT, handler)
    #from signal import signal, SIGTERM
    #signal.signal(signal.SIGTERM, lambda signum, stack_frame: exit(1))
    #signal.signal(signal.SIGTERM, handler)
    #signal.signal(signal.SIGINT, lambda : Gtk.main_quit)
    global log
    cachedir = os.environ.get('XDG_CACHE_HOME','').strip()
    if not cachedir:
        cachedir = os.path.expanduser("~/.cache")
    log_filename = os.path.join(cachedir, "indicator-china-weather.log")
    log = logging.getLogger('IndicatorChinaWeather')
    log.propagate = False
    log.setLevel(logging.DEBUG)
    log_handler = logging.handlers.RotatingFileHandler(log_filename, maxBytes=1024*1024, backupCount=5)
    log_formatter = logging.Formatter("[%(asctime)s - %(levelname)s - %(message)s")
    log_handler.setFormatter(log_formatter)
    log.addHandler(log_handler)

    log.info("--Started UbuntuKylin Weather App from %s --" % os.path.abspath(os.path.curdir))

    # Single instance stuff for weather indicator
    myapp = SingleInstance("/tmp/indicator-china-weather-%d.pid" % os.getuid())
    # check is another instance of same program running
    if myapp.is_already_running():
        log.info("Another instance of this program is already running")
        sys.exit("Another instance of this program is already running")
    #Watcher()
    load_css_sheet_sytle()
    GObject.threads_init()
    Gdk.threads_init()
    Gdk.threads_enter()
    Gtk.init(None)
    iw = IndicatorWeather()
    #iw.setDaemon(True)
    signal.signal(signal.SIGTERM, handler)  
    signal.signal(signal.SIGINT, handler)
    main()
    #Watcher()
    Gdk.threads_leave()
